'use client';
import React, { useRef, useEffect, useMemo } from "react";
import { useGLTF } from "@react-three/drei";
import * as THREE from "three";
import { useThree } from "@react-three/fiber";
import { Group } from "three";

export default function HeartModel({
    url = "/models/heart.glb",
    clipConstant = 0,
}) {
    const gltf = useGLTF(url);
    const group = useRef<Group>(null!);
    const { gl } = useThree();

    // enable local clipping on renderer
    useEffect(() => {
        if (gl) gl.localClippingEnabled = true;
    }, [gl]);

    // create clipping plane
    const clippingPlane = useMemo(() => {
        // plane normal points in -Y: this will make slide up/down visually intuitive
        return new THREE.Plane(new THREE.Vector3(0, -1, 0), clipConstant);
    }, [clipConstant]);

    // apply clipping plane to materials in the model
    useEffect(() => {
        if (!gltf) return;
        gltf.scene.traverse((child:any) => {
            if (child.isMesh && child.material) {
                const mats = Array.isArray(child.material)
                    ? child.material
                    : [child.material];
                mats.forEach((m:any) => {
                    m.clippingPlanes = [clippingPlane];
                    m.clipShadows = true;
                    m.needsUpdate = true;
                });
            }
        });
    }, [gltf, clippingPlane]);

    // optional: scale/center adjustments depending on model
    useEffect(() => {
        if (!gltf) return;
        // auto-scale to a reasonable size (optional)
        const box = new THREE.Box3().setFromObject(gltf.scene);
        const size = new THREE.Vector3();
        box.getSize(size);
        const maxDim = Math.max(size.x, size.y, size.z);
        if (maxDim > 0) {
            const scale = 3 / maxDim; // tweak target size
            gltf.scene.scale.setScalar(scale);
            // center
            const center = new THREE.Vector3();
            box.getCenter(center);
            gltf.scene.position.sub(center.multiplyScalar(scale));
        }
    }, [gltf]);

    return (
        <group ref={group} dispose={null}>
            <primitive object={gltf.scene} />
        </group>
    );
}